package com.ruoyi.deeplearn.component;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.http.OkHttpUtils;
import com.ruoyi.deeplearn.component.modelVo.*;
import com.ruoyi.deeplearn.domain.*;
import com.ruoyi.deeplearn.service.*;
import com.ruoyi.framework.minio.MinioFile;
import com.ruoyi.framework.minio.MinioService;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Component
public class ModelForecastComponent {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private IDeepForecastService deepForecastService;
    @Autowired
    private IDeepAlgorithmService deepAlgorithmService;
    @Autowired
    private IDeepModelVersionService deepModelVersionService;
    @Autowired
    private IDeepModelService deepModelService;
    @Autowired
    private IDeepModelDeployService deepModelDeployService;
    @Autowired
    private IDeepForecastResultService deepForecastResultService;
    @Autowired
    private IDeepForecastResultItemService deepForecastResultItemService;
    @Autowired
    private MinioService minioService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;



    public void publishForecast(Long deepForecastId) {
        redisTemplate.convertAndSend(RedisMqKey.forecast,deepForecastId.toString());
    }

    public void subscribe(Long deepForecastId){
        //使用redis消息队列
        DeepForecast forecast = deepForecastService.selectDeepForecastById(deepForecastId);
        if(forecast==null)return;
        DeepModelVersion modelVersion = deepModelVersionService.
                selectDeepModelVersionById(forecast.getModelVersionId());
        if(modelVersion==null)return;
//        DeepAlgorithm deepAlgorithm = deepAlgorithmService.
//                selectDeepAlgorithmById(modelVersion.getTrainAlgorithmId());
//        if(deepAlgorithm==null)return;
//        if(deepAlgorithm.getPlatform()==2){//pytorch
//            try {
//                publishForecastByPyTorch(forecast,modelVersion,deepAlgorithm);
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }
    }

    /**
     * POST /predictions/{model_name}
     *
     * 模型多个版本接口的REST调用/predictions/{model_name}/{version}：
     *
     *
     * curl -O https://raw.githubusercontent.com/pytorch/serve/master/docs/images/kitten_small.jpg
     *
     * curl http://localhost:8080/predictions/resnet-18 -T kitten_small.jpg
     *
     * or:
     * curl http://localhost:8080/predictions/resnet-18 -F "data=@kitten_small.jpg"or:curl -X POST  http://localhost:8080/predictions/text_cls --data "data=输入字符串"
     * @param forecast
     * @param modelVersion
     * @param deepAlgorithm
     */
    private void publishForecastByPyTorch(DeepForecast forecast,
                                          DeepModelVersion modelVersion,
                                          DeepAlgorithm deepAlgorithm) throws IOException {
        //下载文件
        ResponseEntity<byte[]> download = minioService.
                download(forecast.getBucket(), forecast.getObjectName());
        File forecastFile = new File(forecast.getFileName());
        FileUtils.writeByteArrayToFile(forecastFile,download.getBody());
        //提交预测
        //curl http://121.36.8.195:8080/predictions/fastrcnn -T /home/rsdls/torchserve/fastrcnn/cropped1.JPG
//        File file = new File("C:\\Users\\wwren\\Postman\\files\\cropped1.JPG");
        OkHttpUtils.getInstance().init()
//                .url("http://121.36.8.195:8080/predictions/fastrcnn")
                .url(deepAlgorithm.getForecastUrl()+"/predictions/"+deepAlgorithm.getCode())
                .postFile(null,"data",forecastFile)
                .exec(new OkHttpUtils.OnResponse() {
                    @Override
                    public void onSuccess(Response response) {
                        try {
                            if(response.isSuccessful()){
                                String string = response.body().string();
                                logger.info("publishForecastByPyTorch result ......ok  ");
                                forecast.setEndTime(new Date());
//                                forecast.setForecast(string);
//                                forecast.setStatus(DeepForecast.status_success);
                                deepForecastService.updateDeepForecast(forecast);
                                //根据检测类型处理结果
                                try {
                                    //失败的
                                    //{
                                    //  "code": 503,
                                    //  "type": "InternalServerException",
                                    //  "message": "Prediction failed"
                                    //}
                                    processPyTorchForecastResult(forecast,modelVersion,deepAlgorithm,forecastFile);
                                } catch (Exception e) {
                                    logger.error("parse result error",e);
//                                    forecast.setStatus(DeepForecast.status_error);
                                    deepForecastService.updateDeepForecast(forecast);
                                }
                            }else {
                                //网络异常
                            }
                        } catch (Exception e) {
                            logger.error("parse result error",e);
                            forecast.setStatus(2);
                            deepForecastService.updateDeepForecast(forecast);
                        }
                    }

                    @Override
                    public void onError(Exception e) {
                        logger.error("publish model error",e);
                        forecast.setStatus(2);
                        deepForecastService.updateDeepForecast(forecast);
                    }
                });
    }

    private void processPyTorchForecastResult(
            DeepForecast forecast, DeepModelVersion modelVersion,
            DeepAlgorithm deepAlgorithm, File forecastSrcFile) throws IOException {
//        if(StringUtils.isEmpty(deepAlgorithm.getParseConfig())
//                ||StringUtils.isEmpty(forecast.getForecast())){
//            return;
//        }
//        logger.info("processPyTorchForecastResult................................");
//        List<ParseConfig> parseConfigs = JSON.parseArray(
//                deepAlgorithm.getParseConfig(),ParseConfig.class);
//        //根据不同的算法解析结果--生成预测结果及报告
//        if(DeepClassifyType.type_classify.equals(forecast.getClassifyTypeCode())) {
//            logger.info("---------------classify------------------");
////            [
////            {
////                "alias": "String，标签别名",
////                 "tag": "String，标签",
////                 "probability": "double类型，表示预测结果的预期"
////            }]
//            //照片分类
//            List<ClassificationResult> classificationResults = new ArrayList<>();
//            JSONArray results = JSON.parseArray(forecast.getForecast());
//            for(int i=0;i<results.size();i++){
//                JSONObject result = results.getJSONObject(i);
//                JSONObject data = new JSONObject();
//                parseConfigs.stream().forEach(parseConfig -> {
//                    String value = result.getString(parseConfig.getSource());
//                    data.put(parseConfig.getKey(),value);
//                });
//                ClassificationResult classification = JSON.parseObject(JSON.toJSONBytes(data),ClassificationResult.class);
//                classificationResults.add(classification);
//            }
//            saveClassificationResults(forecast,classificationResults);
//        }
//        else if(DeepClassifyType.type_detection.equals(forecast.getClassifyTypeCode())){
////            [{
////                       "alias": "String，标签别名",
////                        "tag": "String，标签",
////                        "probability": "double类型，表示预测结果的预期",
////                        "x1": "检测标记位置x1",
////                        "y1": "检测标记位置y1",
////                        "x2": "检测标记位置x2",
////                        "y2": "检测标记位置y2"
////            }]
//            logger.info("---------------detection------------------");
//            List<DetectionResult> detectionResults = new ArrayList<>();
//            JSONArray results = JSON.parseArray(forecast.getForecast());
//            logger.info("---------------detection  results size------------------"+results.size());
//            logger.info("---------------detection-----parse config-------------"+deepAlgorithm.getParseConfig());
//            for(int i=0;i<results.size();i++){
//                JSONObject result = results.getJSONObject(i);
//                JSONObject data = new JSONObject();
//                parseConfigs.stream().forEach(parseConfig -> {
//                    try {
//                        String source = parseConfig.getSource();
//                        if(!StringUtils.isEmpty(source)){
//                            if(source.contains("@")){
//                                String[] split = source.split("@");
//                                JSONArray jsonArray = result.getJSONArray(split[0]);
//                                int index = Integer.parseInt(split[1]);
//                                data.put(parseConfig.getKey(),jsonArray.getString(index));
//                            }else {
//                                String value = result.getString(source);
//                                data.put(parseConfig.getKey(),value);
//                            }
//                        }
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                    }
//                });
//                DetectionResult detection = JSON.parseObject(JSON.toJSONBytes(data),DetectionResult.class);
//                detectionResults.add(detection);
////                saveDetectionResults(forecast,detectionResults);
//            }
//            logger.info("forecast result image init .........");
//            //照片检测
//            BufferedImage image = ImageIO.read(forecastSrcFile);
//            //处理
//            Graphics2D graphics = image.createGraphics();
////            Graphics2D graphics2D = graphics;
//            graphics.setColor(Color.YELLOW);
//            graphics.setStroke(new BasicStroke(5));
////            List<FastrcnnVo> data = JSON.parseArray(forecast.getForecast(), FastrcnnVo.class);
////            data.stream().forEach(item->{
////                //x1,y1,x2,y2
////                List<Double> box = item.getBox();
////                //int x, int y, int width, int heigh
////                graphics.drawRect(box.get(0).intValue(),box.get(1).intValue(),
////                        box.get(2).intValue()-box.get(0).intValue(),
////                        box.get(3).intValue()-box.get(1).intValue());
////            });
//            detectionResults.stream().forEach(item->{
//                //x1,y1,x2,y2
////                List<Double> box = item.getBox();
//                //int x, int y, int width, int heigh
//                graphics.drawRect(item.getX1().intValue(),item.getY1().intValue(),
//                        item.getX2().intValue()-item.getX1().intValue(),
//                        item.getY2().intValue()-item.getY1().intValue());
//            });
//            String forecastObjectName = IdUtil.getSnowflakeNextIdStr()+"."+FileUtils.getExt(forecast.getFileName());
//            logger.info("forecast result image upload image ........."+forecastObjectName);
//            File outFile = new File(RuoYiConfig.getTmpPath(),forecastObjectName);
//            File parentFile = outFile.getParentFile();
//            if(!parentFile.exists()){
//                parentFile.mkdirs();
//            }
//            outFile.createNewFile();
//            ImageIO.write(image,FileUtils.getExt(forecast.getFileName()),outFile);
//            MinioFile upload = minioService.uploadFile(new FileInputStream(outFile),
//                    forecast.getBucket(),forecastObjectName );
//            forecast.setForecastObjectName(forecastObjectName);
//            //outFile.delete();
//            deepForecastService.updateDeepForecast(forecast);
//            logger.info("forecast result image .........");
//        }
//        else if(DeepClassifyType.type_partition.equals(forecast.getClassifyTypeCode())){
//            logger.info("---------------partition------------------");
////            [{
////                       "alias": "String，标签别名",
////                        "tag": "String，标签",
////                        "probability": "double类型，表示预测结果的预期",
////                        "x1": "检测标记位置x1",
////                        "y1": "检测标记位置y1",
////                        "x2": "检测标记位置x2",
////                        "y2": "检测标记位置y2"
////            }]
//            logger.info("---------------partition------------------");
//            List<DetectionResult> detectionResults = new ArrayList<>();
//            JSONArray results = JSON.parseArray(forecast.getForecast());
//            logger.info("---------------partition  results size------------------"+results.size());
//            logger.info("---------------partition-----parse config-------------"+deepAlgorithm.getParseConfig());
//            for(int i=0;i<results.size();i++){
//                JSONObject result = results.getJSONObject(i);
//                JSONObject data = new JSONObject();
//                parseConfigs.stream().forEach(parseConfig -> {
//                    try {
//                        String source = parseConfig.getSource();
//                        if(!StringUtils.isEmpty(source)){
//                            if(source.contains("@")){
//                                String[] split = source.split("@");
//                                JSONArray jsonArray = result.getJSONArray(split[0]);
//                                int index = Integer.parseInt(split[1]);
//                                data.put(parseConfig.getKey(),jsonArray.getString(index));
//                            }else {
//                                String value = result.getString(source);
//                                data.put(parseConfig.getKey(),value);
//                            }
//                        }
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                    }
//                });
//                DetectionResult detection = JSON.parseObject(JSON.toJSONBytes(data),DetectionResult.class);
//                detectionResults.add(detection);
////                saveDetectionResults(forecast,detectionResults);
//            }
//            logger.info("forecast result image init .........");
//            //照片检测
//            BufferedImage image = ImageIO.read(forecastSrcFile);
//            //处理
//            Graphics2D graphics = image.createGraphics();
////            Graphics2D graphics2D = graphics;
//            graphics.setColor(Color.YELLOW);
//            AlphaComposite alpha = AlphaComposite.
//                    getInstance(AlphaComposite.SRC_OVER, 0.3f); // 创建透明度对象
//            graphics.setComposite(alpha); // 设置透明度
//            graphics.setStroke(new BasicStroke(5));
//            //paint属性控制填充效果
////            Paint mPaint = new GradientPaint
////            List<FastrcnnVo> data = JSON.parseArray(forecast.getForecast(), FastrcnnVo.class);
////            data.stream().forEach(item->{
////                //x1,y1,x2,y2
////                List<Double> box = item.getBox();
////                //int x, int y, int width, int heigh
////                graphics.drawRect(box.get(0).intValue(),box.get(1).intValue(),
////                        box.get(2).intValue()-box.get(0).intValue(),
////                        box.get(3).intValue()-box.get(1).intValue());
////            });
//            detectionResults.stream().forEach(item->{
//                //x1,y1,x2,y2
////                List<Double> box = item.getBox();
//                //int x, int y, int width, int heigh
//                graphics.fillRect(item.getX1().intValue(),item.getY1().intValue(),
//                        item.getX2().intValue()-item.getX1().intValue(),
//                        item.getY2().intValue()-item.getY1().intValue());
////                graphics.fillRect();
//            });
//            String forecastObjectName = IdUtil.getSnowflakeNextIdStr()+"."+FileUtils.getExt(forecast.getFileName());
//            logger.info("forecast result image upload image ........."+forecastObjectName);
//            File outFile = new File(RuoYiConfig.getTmpPath(),forecastObjectName);
//            File parentFile = outFile.getParentFile();
//            if(!parentFile.exists()){
//                parentFile.mkdirs();
//            }
//            outFile.createNewFile();
//            ImageIO.write(image,FileUtils.getExt(forecast.getFileName()),outFile);
//            MinioFile upload = minioService.uploadFile(new FileInputStream(outFile),
//                    forecast.getBucket(),forecastObjectName );
//            forecast.setForecastObjectName(forecastObjectName);
//            //outFile.delete();
//            deepForecastService.updateDeepForecast(forecast);
//            logger.info("forecast result image .........");
//        }
//        else if(DeepClassifyType.type_recognition.equals(forecast.getClassifyTypeCode())){
//            logger.info("---------------recognition------------------");
////            [{
////                       "alias": "String，标签别名",
////                        "tag": "String，标签",
////                        "probability": "double类型，表示预测结果的预期",
////                        "x1": "检测标记位置x1",
////                        "y1": "检测标记位置y1",
////                        "x2": "检测标记位置x2",
////                        "y2": "检测标记位置y2"
////            }]
//            List<RecognitionResult> recognitionResults = new ArrayList<>();
//            JSONArray results = JSON.parseArray(forecast.getForecast());
//            for(int i=0;i<results.size();i++){
//                JSONObject result = results.getJSONObject(i);
//                JSONObject data = new JSONObject();
//                parseConfigs.stream().forEach(parseConfig -> {
//                    String source = parseConfig.getSource();
//                    if(source.contains("@")){
//                        String[] split = source.split("@");
//                        JSONArray jsonArray = result.getJSONArray(split[0]);
//                        int index = Integer.parseInt(split[1]);
//                        data.put(parseConfig.getKey(),jsonArray.getString(index));
//                    }else {
//                        String value = result.getString(source);
//                        data.put(parseConfig.getKey(),value);
//                    }
//                });
//                RecognitionResult detection = JSON.parseObject(JSON.toJSONBytes(data),RecognitionResult.class);
//                recognitionResults.add(detection);
//                saveRecognitionResult(forecast,recognitionResults);
//            }
//        }
//        else if(DeepClassifyType.type_point_dimension.equals(forecast.getClassifyTypeCode())){
//        }
//        else if(DeepClassifyType.type_line_dimension.equals(forecast.getClassifyTypeCode())){
//        }
//        else if(DeepClassifyType.type_pixel_dimension.equals(forecast.getClassifyTypeCode())){
//            logger.info("---------------pixel_dimension------------------");
//            PixelDimensionResult pixelDimensionResult = new PixelDimensionResult();
//            pixelDimensionResult.setData(forecast.getForecast());
//            savePixelDimensionResult(forecast,pixelDimensionResult);
//        }
    }



    //保存分类结果
    private void saveClassificationResults(DeepForecast forecast, List<ClassificationResult> classificationResults) {
//        if(classificationResults==null||classificationResults.size()==0)return;
//        forecast.setParseResult(JSON.toJSONString(classificationResults));
//        deepForecastService.updateDeepForecast(forecast);
//        DeepForecastResult forecastResult = new DeepForecastResult();
//        forecastResult.setId(IdUtil.getSnowflakeNextId());
//        forecastResult.setForecastId(forecast.getId());
//        forecastResult.setDataTypeId(forecast.getDataTypeId());
//        forecastResult.setClassifyTypeId(forecast.getClassifyTypeId());
//        forecastResult.setParseResult(JSON.toJSONString(classificationResults));
//        deepForecastResultService.insertDeepForecastResult(forecastResult);
//        classificationResults.stream().forEach(item->{
//            DeepForecastResultItem resultItem = new DeepForecastResultItem();
//            resultItem.setId(IdUtil.getSnowflakeNextId());
//            resultItem.setForecastId(forecast.getId());
//            resultItem.setDataTypeId(forecast.getDataTypeId());
//            resultItem.setClassifyTypeId(forecast.getClassifyTypeId());
//            resultItem.setForecastResultId(forecastResult.getId());
//            resultItem.setAlias(item.getAlias());
//            resultItem.setTag(item.getTag());
//            resultItem.setProbability(item.getProbability());
//            //设置tag id
//            deepForecastResultItemService.insertDeepForecastResultItem(resultItem);
//        });
    }

    //保存检测结果
    private void saveDetectionResults(DeepForecast forecast, List<DetectionResult> detectionResults) {
//        if(detectionResults==null||detectionResults.size()==0)return;
//        forecast.setParseResult(JSON.toJSONString(detectionResults));
//        deepForecastService.updateDeepForecast(forecast);
//        DeepForecastResult forecastResult = new DeepForecastResult();
//        forecastResult.setId(IdUtil.getSnowflakeNextId());
//        forecastResult.setForecastId(forecast.getId());
//        forecastResult.setDataTypeId(forecast.getDataTypeId());
//        forecastResult.setClassifyTypeId(forecast.getClassifyTypeId());
//        forecastResult.setParseResult(JSON.toJSONString(detectionResults));
//        deepForecastResultService.insertDeepForecastResult(forecastResult);
//        detectionResults.stream().forEach(item->{
//            DeepForecastResultItem resultItem = new DeepForecastResultItem();
//            resultItem.setId(IdUtil.getSnowflakeNextId());
//            resultItem.setForecastId(forecast.getId());
//            resultItem.setDataTypeId(forecast.getDataTypeId());
//            resultItem.setClassifyTypeId(forecast.getClassifyTypeId());
//            resultItem.setForecastResultId(forecastResult.getId());
//            resultItem.setAlias(item.getAlias());
//            resultItem.setTag(item.getTag());
//            resultItem.setProbability(item.getProbability());
//            resultItem.setX1(item.getX1());
//            resultItem.setY1(item.getY1());
//            resultItem.setX2(item.getX2());
//            resultItem.setY2(item.getY2());
//            deepForecastResultItemService.insertDeepForecastResultItem(resultItem);
//        });
    }

    //保存检测结果
    private void saveRecognitionResult(DeepForecast forecast, List<RecognitionResult> recognitionResults) {
//        if(recognitionResults==null||recognitionResults.size()==0)return;
//        forecast.setParseResult(JSON.toJSONString(recognitionResults));
//        deepForecastService.updateDeepForecast(forecast);
//        DeepForecastResult forecastResult = new DeepForecastResult();
//        forecastResult.setId(IdUtil.getSnowflakeNextId());
//        forecastResult.setForecastId(forecast.getId());
//        forecastResult.setDataTypeId(forecast.getDataTypeId());
//        forecastResult.setClassifyTypeId(forecast.getClassifyTypeId());
//        forecastResult.setParseResult(JSON.toJSONString(recognitionResults));
//        deepForecastResultService.insertDeepForecastResult(forecastResult);
//        recognitionResults.stream().forEach(item->{
//            DeepForecastResultItem resultItem = new DeepForecastResultItem();
//            resultItem.setId(IdUtil.getSnowflakeNextId());
//            resultItem.setForecastId(forecast.getId());
//            resultItem.setDataTypeId(forecast.getDataTypeId());
//            resultItem.setClassifyTypeId(forecast.getClassifyTypeId());
//            resultItem.setForecastResultId(forecastResult.getId());
//            resultItem.setAlias(item.getAlias());
//            resultItem.setTag(item.getTag());
//            resultItem.setProbability(item.getProbability());
//            resultItem.setX1(item.getX1());
//            resultItem.setY1(item.getY1());
//            resultItem.setX2(item.getX2());
//            resultItem.setY2(item.getY2());
//            deepForecastResultItemService.insertDeepForecastResultItem(resultItem);
//        });
    }


    //保存像素结果
    private void savePixelDimensionResult(DeepForecast forecast, PixelDimensionResult pixelDimensionResult) {
//        if(forecast==null||pixelDimensionResult==null)return;
//        forecast.setParseResult(JSON.toJSONString(pixelDimensionResult));
//        deepForecastService.updateDeepForecast(forecast);
//        DeepForecastResult forecastResult = new DeepForecastResult();
//        forecastResult.setId(IdUtil.getSnowflakeNextId());
//        forecastResult.setForecastId(forecast.getId());
//        forecastResult.setDataTypeId(forecast.getDataTypeId());
//        forecastResult.setClassifyTypeId(forecast.getClassifyTypeId());
//        forecastResult.setParseResult(JSON.toJSONString(pixelDimensionResult));
//        deepForecastResultService.insertDeepForecastResult(forecastResult);
//        DeepForecastResultItem resultItem = new DeepForecastResultItem();
//        resultItem.setId(IdUtil.getSnowflakeNextId());
//        resultItem.setForecastId(forecast.getId());
//        resultItem.setDataTypeId(forecast.getDataTypeId());
//        resultItem.setClassifyTypeId(forecast.getClassifyTypeId());
//        resultItem.setForecastResultId(forecastResult.getId());
//        deepForecastResultItemService.insertDeepForecastResultItem(resultItem);
    }
}
